/*
 * comm_system.cpp
 *
 *  Created on: 2010-1-7
 *      Author: gavinkwoe
 */

#include "comm_features.h"

#if (__COMM_TARGET__ == __TARGET_SYMBIAN)

#include "comm_std.h"
#include "comm_mem.h"
#include "comm_objbase.h"
#include "comm_llist.h"

//#include <stdlib.h>

/*************************************************************************
* IMPLEMENTATION
*************************************************************************/

/*************************************************************************
* DESCRIPTION
*	$$__FUNC_DESC__$$
*************************************************************************/
COMM_EXPORT void comm_ll_push_head( comm_llist_ptr_t list, comm_llink_ptr_t link )
{
	if ( NULL == list || NULL == link )
		return;

	link->prev = NULL;
	link->next = list->head;

	if ( NULL != list->head )
	{
		list->head->prev = link;
	}

	list->head = link;

	if ( NULL == list->tail )
	{
		list->tail = link;
	}

	list->count	+= 1;
}

/*************************************************************************
* DESCRIPTION
*	$$__FUNC_DESC__$$
*************************************************************************/
COMM_EXPORT void comm_ll_push_tail( comm_llist_ptr_t list, comm_llink_ptr_t link )
{
	if ( NULL == list || NULL == link )
		return;
	
	link->prev = list->tail;
	link->next = NULL;

	if ( NULL != list->tail )
	{
		list->tail->next = link;
	}

	list->tail = link;

	if ( NULL == list->head )
	{
		list->head = link;
	}

	list->count += 1;
}

/*************************************************************************
* DESCRIPTION
*	$$__FUNC_DESC__$$
*************************************************************************/
COMM_EXPORT comm_llink_ptr_t comm_ll_pop_head( comm_llist_ptr_t list )
{
	comm_llink_ptr_t node = NULL;

	if ( NULL == list )
		return NULL;
	
	if ( NULL == list->head )
		return NULL;
	
	node = list->head;
	list->head = list->head->next;

	if ( NULL != list->head )
	{
		list->head->prev = NULL;
	}
        
	if ( list->tail == node )
	{
		list->tail = NULL;
	}

	list->count -= 1;
	return node;
}

/*************************************************************************
* DESCRIPTION
*	$$__FUNC_DESC__$$
*************************************************************************/
COMM_EXPORT comm_llink_ptr_t comm_ll_pop_tail( comm_llist_ptr_t list )
{
	comm_llink_ptr_t node = NULL;
	
	if ( NULL == list )
		return NULL;
	
	if ( NULL == list->tail )
		return NULL;

	node = list->tail;
	list->tail = list->tail->prev;	
	
	if ( NULL != list->tail )
	{
		list->tail->next = NULL;
	}
	
	if ( list->head == node )
	{
		list->head = NULL;
	}
	
	list->count -= 1;
	return node;
}

/*************************************************************************
* DESCRIPTION
*	$$__FUNC_DESC__$$
*************************************************************************/
COMM_EXPORT void comm_ll_insert( comm_llist_ptr_t list, comm_llink_ptr_t pos, comm_llink_ptr_t link )
{
	if ( NULL == list || NULL == link )
		return;
	
	if ( NULL == pos )
	{
		comm_ll_push_head( list, link );
	}
	else
	{
		link->prev = pos;
		link->next = pos->next;

		if ( NULL != pos->next )
		{
			pos->next->prev = link;
		}

		pos->next = link;

		if ( pos == list->tail )
		{
			list->tail = link;
		}

		list->count += 1;
	}
}

/*************************************************************************
* DESCRIPTION
*	$$__FUNC_DESC__$$
*************************************************************************/
COMM_EXPORT void comm_ll_remove( comm_llist_ptr_t list, comm_llink_ptr_t link )
{
	if ( NULL == list || NULL == link )
		return;
	
	if ( 0 == list->count )
		return;

	if ( list->head == link )
	{
		list->head = link->next;
	}

	if ( list->tail == link )
	{
		list->tail = link->prev;
	}
	
	if ( NULL != link->prev )
	{
		link->prev->next = link->next;
	}

	if ( NULL != link->next )
	{
		link->next->prev = link->prev;
	}

	link->prev = NULL;
	link->next = NULL;

	list->count -= 1;
}

/*************************************************************************
* DESCRIPTION
*	$$__FUNC_DESC__$$
*************************************************************************/
COMM_EXPORT void comm_ll_sort( comm_llist_ptr_t list, comm_cmp_fptr_t cmp_func )
{
	unsigned long		i;
	comm_llink_ptr_t	curr;
	comm_llink_ptr_t *	temp_arr;

	if ( NULL == list || NULL == cmp_func )
		return;
	
	if ( 0 == list->count )
		return;

	temp_arr = (comm_llink_ptr_t *)COMM_HEAP_ALLOC( sizeof(comm_llink_ptr_t) * list->count );
	if ( NULL == temp_arr )
		return;

	for ( i = 0, curr = list->head; NULL != curr; ++i, curr = curr->next )
	{
		temp_arr[i] = curr;
	}

	qsort( (void *)&temp_arr[0], list->count, sizeof(comm_llink_ptr_t), cmp_func );

	COMM_LLIST_INIT( list );

	for ( i = 0; i < list->count; ++i )
	{
		comm_ll_push_tail( list, temp_arr[i] );
	}

	COMM_HEAP_FREE( temp_arr );
}

#endif	// #if (__COMM_TARGET__ == __TARGET_SYMBIAN)
